package com.gzq.common_core.base;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.gzq.common_core.BuildConfig;
import com.gzq.common_core.base.config.CrashManagerConfig;
import com.gzq.common_core.base.config.GsonConfig;
import com.gzq.common_core.base.config.OkhttpConfig;
import com.gzq.common_core.base.config.RetrofitConfig;
import com.gzq.common_core.base.config.SessionManagerConfig;
import com.gzq.common_core.base.config.ToastConfig;
import com.gzq.common_core.constant.Constants;
import com.gzq.common_core.crash.CaocConfig;
import com.gzq.common_core.http.interceptor.Level;
import com.gzq.common_core.http.interceptor.LoggingInterceptor;
import com.gzq.common_core.log.CrashReportingTree;
import com.gzq.common_core.session.SessionManager;
import com.gzq.common_core.toast.T;

import java.util.concurrent.TimeUnit;

import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.unit.Subunits;
import me.jessyan.retrofiturlmanager.RetrofitUrlManager;
import okhttp3.OkHttpClient;
import okhttp3.internal.platform.Platform;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import timber.log.Timber;

final class ObjectFactory {
    private static volatile ObjectFactory instance;

    public static ObjectFactory instance() {
        if (instance == null) {
            synchronized (ObjectFactory.class) {
                if (instance == null) {
                    instance = new ObjectFactory();
                }
            }
        }
        return instance;
    }

    private GsonBuilder gsonBuilder;
    private OkHttpClient.Builder okhttpBuilder;
    private Retrofit.Builder retrofitBuilder;
    private CaocConfig.Builder crashBuilder;


    public Gson getGson(GlobalModel globalConfig) {
        GsonConfig gsonConfig = globalConfig.getGsonConfig();
        if (gsonConfig != null) {
            if (gsonBuilder == null) gsonBuilder = new GsonBuilder();
            gsonConfig.gson(App.getApp(), gsonBuilder);
        }
        return gsonBuilder.create();
    }

    public OkHttpClient getOkHttpClient(GlobalModel globalConfig) {
        if (okhttpBuilder == null) okhttpBuilder = new OkHttpClient.Builder();
        okhttpBuilder
                .connectTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true);
        OkhttpConfig okhttpConfig = globalConfig.getOkhttpConfig();
        if (okhttpConfig != null) {
            okhttpConfig.okhttp(App.getApp(), okhttpBuilder);
        }
        if (BuildConfig.DEBUG) {
            okhttpBuilder.addInterceptor(getLoggingInterceptor());
        }
        //添加动态变更BaseUrl的能力
        RetrofitUrlManager.getInstance().with(okhttpBuilder).build();
        return okhttpBuilder.build();
    }

    public Retrofit getRetrofit(GlobalModel globalConfig) {
        String baseUrl = globalConfig.getBaseUrl();
        if (TextUtils.isEmpty(baseUrl)) {
            throw new NullPointerException("baseUrl is null");
        }
        if (retrofitBuilder == null) retrofitBuilder = new Retrofit.Builder();
        retrofitBuilder.baseUrl(baseUrl);
        OkHttpClient okHttpClient = getOkHttpClient(globalConfig);
        retrofitBuilder.client(okHttpClient);
        RetrofitConfig retrofitConfig = globalConfig.getRetrofitConfig();
        if (retrofitConfig != null) {
            retrofitConfig.retrofit(App.getApp(), retrofitBuilder);
        }
        retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
        retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
        return retrofitBuilder.build();
    }

    public void initSessionManager(GlobalModel globalConfig) {
        //默认使用MMKV作为本地缓存的工具
        SessionManager.instance().init();
        SessionManagerConfig sessionManagerConfig = globalConfig.getSessionManagerConfig();
        if (sessionManagerConfig != null) {
            sessionManagerConfig.session(App.getApp(), SessionManager.instance());
        }
    }

    public void initCrashManager(GlobalModel globalConfig) {
        if (crashBuilder == null) crashBuilder = CaocConfig.Builder.create();
        crashBuilder
                //背景模式,开启沉浸式
                .backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT)
                //是否启动全局异常捕获
                .enabled(true)
                //是否显示错误详细信息
                .showErrorDetails(true)
                //是否显示重启按钮
                .showRestartButton(true)
                //是否跟踪Activity
                .trackActivities(true)
                //崩溃的间隔时间(毫秒)
                .minTimeBetweenCrashesMs(2000);
        //错误图标
//                .errorDrawable(R.drawable.ic_error);
        CrashManagerConfig crashManagerConfig = globalConfig.getCrashManagerConfig();
        if (crashManagerConfig != null) {
            crashManagerConfig.crash(App.getApp(), crashBuilder);
        }
        crashBuilder.apply();
    }

    public LoggingInterceptor getLoggingInterceptor() {
        return new LoggingInterceptor.Builder()
                .loggable(BuildConfig.DEBUG)
                .setLevel(Level.BASIC)
                .log(Platform.WARN)
                .request("Request")
                .response("Response")
                .enableAndroidStudio_v3_LogsHack(true)
                .build();
    }

    public void initAutoSize(GlobalModel globalConfig) {
        boolean isSupportDP = globalConfig.isSupportDP();
        boolean isSupportSP = globalConfig.isSupportSP();
        Subunits subunits = globalConfig.getSubunits();
        AutoSizeConfig.getInstance()
                .setCustomFragment(true)
                .getUnitsManager()
                .setSupportDP(isSupportDP)
                .setSupportSP(isSupportSP)
                .setSupportSubunits(subunits);
    }

    public void initTimber() {
        if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        } else {
            Timber.plant(new CrashReportingTree());
        }
    }

    public void initToast(GlobalModel globalModel) {
        T.instance().init(App.getApp());
        ToastConfig toastConfig = globalModel.getToastConfig();
        if (toastConfig != null) {
            toastConfig.toast(App.getApp(), T.instance());
        }
    }

    public void clear() {
        gsonBuilder = null;
        okhttpBuilder = null;
        retrofitBuilder = null;
    }
}
